home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / vol_400 / 425_01 / tar / restore.c < prev    next >
Text File  |  1994-04-02  |  16KB  |  571 lines

  1. /* restore.c - extract regular files from (tape) archive.
  2.  * This is a part of the Tar program (see file tar.c)
  3.  * Author: T.V.Shaporev
  4.  * Creation date: 11 Mar 1993
  5.  */
  6. #include <stdio.h>
  7. #include <errno.h>
  8.  
  9. #include "sysup.h"
  10. #include "modern.h"
  11. #ifdef MODERN
  12. #    include <string.h>
  13. #else
  14.     char *strncpy();
  15.     int  strlen();
  16. #endif
  17.  
  18. #ifdef MSDOS
  19. #    include <io.h>
  20. #    include <dos.h>
  21. #    include <stdlib.h>
  22. #    ifdef __TURBOC__
  23. #        include <dir.h>
  24. #    else
  25. #        include <direct.h>
  26. #    endif
  27. #else
  28.     int  access(), creat(), open(), close(), link(), unlink();
  29.     int  write(), chown(), utime();
  30.     char *malloc();
  31.         long lseek();
  32.     void free();
  33. #endif
  34.  
  35. #include "lzwbits.h"
  36. #include "lzwhead.h"
  37. #include "compress.h"
  38. #include "define.h"
  39. #include "lzpack.h"
  40.  
  41. char ofname[MAXTNAME
  42. #ifdef MSDOS
  43.             +MAXFILE
  44. #endif
  45.             +1];
  46.  
  47. void extwrerr()
  48. {
  49.    (void)fprintf(myout, "Tar: error extracting \'%s\'\n", ofname);
  50.    done(EWRITE);
  51. }
  52.  
  53. #ifdef MSDOS
  54. static void setime __ARGS__(( int, long ));
  55.  
  56. static void setime(h, mt)
  57. int h; long mt;
  58. {
  59.    struct date d;
  60.    struct time t;
  61.    struct ftime f;
  62.  
  63.    if (m_flag) return;
  64.    unixtodos(mt, &d, &t);
  65.    f.ft_tsec  = t.ti_sec;
  66.    f.ft_min   = t.ti_min;
  67.    f.ft_hour  = t.ti_hour;
  68.    f.ft_day   = d.da_day;
  69.    f.ft_month = d.da_mon;
  70.    f.ft_year  = d.da_year - 1980;
  71.    (void)setftime(h, &f);
  72. }
  73.  
  74. #define wcnt_type unsigned short
  75. #define MAXWARN  8
  76.  
  77. static renamed = FALSE;
  78. static wcnt_type wcount = 0;
  79. static nwarn = 0;
  80.  
  81. static struct { wcnt_type lru; char wnm[MAXTNAME]; } wlist[MAXWARN];
  82.  
  83. static void wrename __ARGS__(( char * ));
  84.  
  85. static void wrename(n)
  86. char *n;
  87. {
  88.    register i;
  89.  
  90.    renamed = FALSE;
  91.    for (i=0; i<nwarn; i++) {
  92.      if (strncmp(wlist[i].wnm, n, MAXTNAME) == 0) {
  93.         wlist[i].lru = wcount++; return;
  94.      }
  95.    }
  96.    (void)printf("Tar: warning: renamed to \'%s\'\n", n);
  97.    if (nwarn < MAXWARN) {
  98.       i = nwarn++;
  99.    } else {
  100.       register j;
  101.       /* Find the least recently used entry */
  102.       for (i=0, j=1; j<MAXWARN; j++) {
  103.          if (wlist[j].lru < wlist[i].lru) i = j;
  104.       }
  105.    }
  106.    (void)strncpy(wlist[i].wnm, n, MAXTNAME);
  107.    wlist[i].lru = wcount++;
  108. }
  109.  
  110. #define CH_DOT '-'
  111. #define CH_BAD '$'
  112.  
  113. static void uname __ARGS__(( char * ));
  114.  
  115. static void uname(fname) /* convert UNIX file name to DOS */
  116. char fname[];
  117. {
  118.    static char invalid[] = "^+=/[]:;\',?*\\<>|\".";
  119.    register char *p = fname;
  120.    register i, offext/* offset to file name extension */;
  121.    register j, limcpy, tmpren;
  122.  
  123.    if (p[1] == ':' && (p[0]>='A' && p[0]<='Z' || p[0]>='a' && p[0]<='z'))
  124.       p += 2;
  125.  
  126.    tmpren = FALSE;
  127.    while (*p) {
  128.       if (*p == '/') {
  129.          ++p; /* Forget dir name changes */ tmpren = FALSE;
  130.       }
  131.  
  132.       for (offext=i=0; p[i] && p[i]!='/'; i++) {
  133.          if (p[i] == '.') {
  134.             if (i == 0) {
  135.                if (p[1]=='.' && p[2]=='/') {
  136.                   /* This is '..' directory, skip */ ++i;
  137.                } else if (p[1]!='/') {
  138.                   /* This is not current directory */
  139.                   p[0] = CH_DOT; tmpren = TRUE;
  140.                }
  141.             } else {
  142.                if (offext) {
  143.                   p[offext] = CH_DOT; tmpren = TRUE;
  144.                }
  145.                offext = i;
  146.             }
  147.          } else if (p[i]<=' ' || p[i]>'~' || strchr(invalid, p[i])) {
  148.             p[i] = CH_BAD; tmpren = TRUE;
  149.          }
  150.       }
  151.       if (!offext) offext = i;
  152.       limcpy = MAXTNAME - (int)(p-fname) - offext;
  153.       i -= offext;
  154.       if (offext <= 8) {
  155.          j = offext;
  156.       } else {
  157.          (void)strncpy(p+8, p+offext, i>4 ? 4 : limcpy);
  158.          tmpren = TRUE;
  159.          j = 8;
  160.       }
  161.       if (i <= 4) {
  162.          j += i;
  163.       } else {
  164.          (void)strncpy(p+(offext>8 ? 12 : offext+4), p+i+offext, limcpy-i);
  165.          tmpren = TRUE;
  166.          j += 4;
  167.       }
  168.       p += j;
  169.    }
  170.    if (tmpren) renamed = TRUE;
  171. }
  172. #else
  173. #    define setime(h,t)
  174. #    define uname(s)
  175. #endif
  176.  
  177. int makedir __ARGS__((char *, int));
  178. int testdir __ARGS__((char *));
  179.  
  180. /*ARGSUSED*/ int makedir(p, to_print)
  181. char *p; int to_print;
  182. {
  183. #ifdef UNIX
  184. #   ifdef RMKDIR
  185.          if (mkdir(p, 0777) != 0 && to_print) {
  186.             (void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
  187.             return ERROR;
  188.          }
  189. #   else
  190.          switch (bincall("mkdir", p)) {
  191.             case  0: break;
  192.             case -1: (void)fprintf(myout, "Tar: fault run mkdir!\n");
  193.             default: done(0);
  194.          }
  195. #   endif
  196.          if (!o_flag) (void)chown(p,(int)st.st_uid,(int)st.st_gid);
  197. #endif
  198. #ifdef MSDOS
  199.          if (mkdir(p) != 0 && to_print) {
  200.             (void)fprintf(myout, "Tar: can\'t create directory \'%s\'\n", p);
  201.             return ERROR;
  202.          }
  203. #endif
  204.    return 0;
  205. }
  206.  
  207. int testdir(p)
  208. char *p;
  209. {
  210.    register j;
  211.    register k = FALSE;
  212. #ifndef UNIX
  213.    register char *q = p;
  214. #endif
  215. #ifdef MSDOS
  216.    renamed = FALSE;
  217. #endif
  218.    for (j=1; j<MAXTNAME && p[j]; j++) {/* check directories */
  219.       if (p[j] == '/') {
  220.          p[j] = 0;
  221. #ifndef UNIX
  222.          uname(q); q = p + j + 1;
  223. #endif
  224.          if (access(p, 1) < 0) {
  225.             if (makedir(p, TRUE) != 0) return ERROR;
  226.             k = TRUE;
  227.          }
  228.          p[j] = '/';
  229.       }
  230.    }
  231. #ifdef MSDOS
  232.    if (renamed && v_flag) wrename(p);
  233. #endif
  234.    return k;
  235. }
  236.  
  237. long thisread;
  238.  
  239. int arcget __ARGS__((void))
  240. {
  241.    if (v_flag && !(thisread & 07777)) percent(thisread, st.st_size);
  242.    return thisread<st.st_size ? (++thisread, readbyte()) : EOF;
  243. }
  244.  
  245. static int  o_file, indput;
  246. static long thiscsum;
  247.  
  248. static void dstput(c)
  249. int c;
  250. {
  251.    thiscsum += c; ((unsigned char *)pk_out)[indput++] = c;
  252.    if (indput >= pksize) {
  253.       if (write(o_file, pk_out, pksize) != pksize) {
  254.          if (v_flag) (void)fprintf(myout, "\n");
  255.          extwrerr();
  256.       }
  257.       indput = 0;
  258.    }
  259. }
  260.  
  261. #define savename(s) ((void)strncpy(ofname,(s),MAXTNAME),ofname[MAXTNAME]='\0')
  262.  
  263. static int newfile __ARGS__(( char *, int ));
  264.  
  265. static int newfile(name, mode)
  266. char *name; int mode;
  267. {
  268. #ifdef MSDOS
  269.    int h, caccess;
  270.    unsigned cmode;
  271.    register k = 0;
  272.  
  273.    savename(name);
  274.    caccess = o_flag ? O_CREAT+O_EXCL+O_WRONLY+O_BINARY :
  275.                       O_CREAT+O_TRUNC+O_WRONLY+O_BINARY;
  276.    cmode = (mode & 0444 ? S_IREAD  : 0) |
  277.            (mode & 0222 ? S_IWRITE : 0) |
  278.            (mode & 0111 ? S_IEXEC  : 0);
  279.    if ((h = open(name, caccess, cmode)) < 0) {
  280.       if (errno == ENOENT || errno == ENOPATH) {
  281.          if ((k=testdir(name)) == TRUE) h = open(name, caccess, cmode);
  282.       } else if (errno == EEXIST && o_flag) {
  283.          static char del[4] = "^~\'`";
  284.          register unsigned ntry = 0;
  285.          register nb, len, i, j;
  286.          char suffix[5];
  287.  
  288.          if ((len = strlen(name)) > MAXTNAME) goto end;
  289.          for (nb=len; nb>0 && name[nb-1]!='/' && name[nb-1]!=':'; nb--) {
  290.             if (name[nb] == '.') len = nb;
  291.          }
  292.          len -= nb;
  293.          do {
  294.             ++ntry;
  295.             /* Convert number of try into suffix */
  296.             suffix[0] = del[ntry & 3];
  297.             for (i=1, j=ntry>>2; j; j>>=5) {
  298.                suffix[i++] = ((j & 037) < 10 ? '0': 'A'-10) + (j & 037);
  299.             }
  300.             suffix[i] = '\0';
  301.             /* Replace end of the name by suffix */
  302.             if (len < 8) {
  303.                (void)strcat(
  304.                         strcpy(ofname+nb+(len+i<8 ? len : 8-i), suffix),
  305.                         name+nb+len);
  306.             } else {
  307.                (void)strncpy(ofname+nb+len-i, suffix, i);
  308.             }
  309.             renamed = TRUE;
  310.             h = open(ofname, caccess, cmode);
  311.          } while (h<0 && errno == EEXIST && ntry);
  312.       }
  313.    }
  314. end:
  315.    if (h < 0) {
  316.       if (k!=ERROR) (void)fprintf(myout,"Tar: can\'t create \'%s\'\n",name);
  317.    } else {
  318.       if (renamed && v_flag) wrename(ofname);
  319.       if ((mode & 0777) == 0) (void)_chmod(name, 1, FA_HIDDEN);
  320.    }
  321.    return h;
  322. #else
  323.    register j = 0;
  324.    register h;
  325.  
  326.    savename(name);
  327.    do {
  328.       if ((h = creat(name, (int)(mode & 07777))) >